#pragma once
#include "acceptor.hpp"
#include "connection.hpp"
#include "loopThreadPool.hpp"

class TcpServer
{
private:
    using ConnectedCallback = std::function<void(const PtrConnection&)>;
    using MessageCallback = std::function<void(const PtrConnection&, Buffer*)>;
    using ClosedCallback = std::function<void(const PtrConnection&)>;
    using EventCallback = std::function<void(const PtrConnection&)>;

private:
    //每当accept到新的客户端连接时，创建Connection对象进行通信
    void NewConnection(int fd)
    {
        _next_id++;
        // 在线程池中轮询一个线程对应的loop保证Connection各个操作的线程安全
        PtrConnection conn(new Connection(_next_id, fd, _pool.NextLoop()));
        conn->SetConnectedCallback(_connected_callback);
        conn->SetMessageCallback(_message_callback);
        conn->SetCloseCallback(_close_callback);
        conn->SetEventCallback(_event_callback);
        conn->SetServerCloseCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));
        if(_enable_inactive_release == true)
            conn->EnableInactiveRelease(_timeout);
        //开始从客户端接受数据
        conn->Established();
        _conns.insert(std::make_pair(_next_id, conn));
    }

    //将Connection对象在Connection集合中移除
    void RemoveConnectionInLoop(const PtrConnection& conn)
    {
        int id = conn->GetId();
        auto it = _conns.find(id);
        if(it != _conns.end())
            _conns.erase(it);
    }

    void RemoveConnection(const PtrConnection& conn)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }
    
public:
    TcpServer(int port)
    :_port(port), _acceptor(&_baseloop, port), _pool(&_baseloop)
    { }

    void SetThreadCount(size_t count) { _pool.SetThreadCount(count); }
    void SetConnectedCallback(const ConnectedCallback& conn_cb) { _connected_callback = conn_cb; }
    void SetMessageCallback(const MessageCallback& mess_cb) { _message_callback = mess_cb; }
    void SetCloseCallback(const ClosedCallback& close_cb)   { _close_callback = close_cb; }
    void SetEventCallback(const EventCallback& event_cb)    { _event_callback = event_cb; }

    //启动超时销毁
    void EnableInactiveRelease(size_t timeout)
    {
        _timeout = timeout;
        _enable_inactive_release = true;
    }
    
    void Start()
    {
        _pool.Create();
        _acceptor.SetAcceptCallBack(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1)); 
        _acceptor.Listen();
        _baseloop.Start();
    }   

private:
    uint64_t _next_id = 0; //时间轮id，用于添加新连接
    int _port;
    int _timeout; //非活跃连接的超时释放超时时间
    bool _enable_inactive_release = false; //非活跃连接的超时释放
    EventLoop _baseloop; //用于接受并派发任务，当线程池大小为 0 则自己处理，不为 0 则由线程池中的loop处理
    Acceptor _acceptor;
    LoopThreadPool _pool;
    std::unordered_map<uint64_t, PtrConnection> _conns;

    ConnectedCallback _connected_callback; 
    MessageCallback _message_callback;
    ClosedCallback _close_callback; 
    EventCallback _event_callback;
};